home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 2000 July / macformat-092.iso / Dreamweaver 3 / Configuration / Commands / Sort Table.js < prev    next >
Encoding:
Text File  |  1999-12-01  |  11.4 KB  |  350 lines

  1. //*************** GLOBAL VARS  *****************
  2.  
  3. var helpDoc = MM.HELP_cmdSortTable;
  4.  
  5. var HAVE_SORTED_BY = new Array(7);
  6.  
  7. //******************* API **********************
  8.  
  9. function commandButtons(){
  10.    var tableObj = findTable();
  11.    var retArr = new Array(BTN_OK,     "sortAndClose()",
  12.                           BTN_Apply,   "sortTable()",
  13.                           BTN_Cancel,  "window.close()",
  14.                           BTN_Help,    "displayHelp()");
  15.  
  16.    //display buttons that can only close the dialog if there are problems with table format
  17.    if (hasSpans(tableObj) || isInvalidTable(tableObj) || hasCaption(tableObj))  
  18.      retArr=new Array(BTN_OK,"window.close()",BTN_Cancel,"window.close()");
  19.  
  20.      return retArr;
  21. }
  22.  
  23. function canAcceptCommand(){
  24.   if (findTable())
  25.     return true;
  26.   else
  27.     return false;
  28. }
  29. //***************** LOCAL FUNCTIONS  ******************
  30.  
  31. function findTable(){
  32.   var tableObj="";
  33.   var selArr = dreamweaver.getSelection();
  34.   var selObj = dreamweaver.offsetsToNode(selArr[0],selArr[1]);
  35.  
  36.   while (tableObj=="" && selObj.parentNode){
  37.     if (selObj.nodeType == Node.ELEMENT_NODE && selObj.tagName=="TABLE")
  38.       tableObj=selObj;
  39.     else
  40.       selObj = selObj.parentNode;
  41.   }
  42.   return tableObj;
  43. }
  44.  
  45. function sortAndClose(){
  46.   //If the current sort has already been applied, close the dialog
  47.   //otherwise, sort
  48.   if (findObject("sortCol").selectedIndex==HAVE_SORTED_BY[0] &&
  49.       findObject("subsortCol").selectedIndex-1==HAVE_SORTED_BY[1] &&
  50.       findObject("sortType").selectedIndex==HAVE_SORTED_BY[2] &&
  51.       findObject("subsortType").selectedIndex==HAVE_SORTED_BY[3] &&
  52.       findObject("sortOrder").selectedIndex==HAVE_SORTED_BY[4] &&
  53.       findObject("subsortOrder").selectedIndex==HAVE_SORTED_BY[5]&&
  54.       findObject("sortFirstRow").checked==HAVE_SORTED_BY[6]){
  55.       window.close();
  56.       }
  57.    else{
  58.      sortTable();
  59.      window.close();
  60.    }
  61.  
  62. }
  63.  
  64. function sortTable(){
  65.     var tableObj, rowCount, rowIter, rowArray, tdIter;
  66.     var rowNode, colIter, sortCol,subsortCol,rowHTML,bSkipFirstRow;
  67.     var textString,startCount,currRow,bMoveRowAttrs;
  68.     
  69.     MM.setBusyCursor();
  70.     
  71.     // Get the selected table
  72.     tableObj = findTable();
  73.  
  74.  
  75.     // Determine number of rows 
  76.     rowIter = tableObj.childNodes; //rowIter is array of TR tags in this table
  77.     rowCount = rowIter.length;
  78.     bSkipFirstRow = !findObject("sortFirstRow").checked;
  79.     bMoveRowAttrs = findObject("moveRowAttrs").checked;
  80.     rowCount = (bSkipFirstRow)?rowCount-1:rowCount;
  81.  
  82.     // Determine column and subsort column
  83.     sortCol = findObject("sortCol").selectedIndex;
  84.     subsortCol = findObject("subsortCol").selectedIndex-1;
  85.  
  86.     //Create a two-dimensional array containing rowCount rows and 3 columns.
  87.     //The first column contains the HTML text for the row,the second
  88.     //column contains the contents of column number sortCol for that row,
  89.     //and the third column contains the contents of column number subsortColumn
  90.     //for that row. 
  91.  
  92.     rowArray = new Array();
  93.     for (i=0;i<rowCount;i++) {
  94.  
  95.        // Copy row text into rowArray
  96.        rowArray[i] = new Array();
  97.        rowHTML = (bSkipFirstRow)?rowIter.item(i+1):rowIter.item(i);  
  98.        rowArray[i][0] = (bMoveRowAttrs)?rowHTML.outerHTML:rowHTML.innerHTML;
  99.  
  100.        // Copy sort key into rowArray
  101.        colIter = rowHTML.childNodes;
  102.        textString=getTextNode(colIter.item(sortCol));
  103.        rowArray[i][1] = findObject("sortType").selectedIndex==0 ?
  104.          gobbleWhiteSpace(textString):parseNumber(gobbleWhiteSpace(textString));
  105.       
  106.        //copy subsort key into rowArray, if applicable
  107.        if (findObject("subsortCol").selectedIndex > 0){
  108.          textString=getTextNode(colIter.item(subsortCol));
  109.          rowArray[i][2]= findObject("subsortType").selectedIndex==0 ?
  110.             gobbleWhiteSpace(textString):parseNumber(gobbleWhiteSpace(textString));
  111.  
  112.        }        
  113.     }
  114.  
  115.     // Sort the rowArray, based on sort key
  116.     rowArray.sort(compareCallback);
  117.  
  118.     // Copy the contents of the sorted rowArray back into the HTML document
  119.     for (i = 0; i < rowCount; i++) {
  120.       currRow=(bSkipFirstRow)?rowIter.item(i+1):rowIter.item(i);
  121.       if (bMoveRowAttrs)
  122.         currRow.outerHTML=rowArray[i][0];
  123.       else
  124.         currRow.innerHTML=rowArray[i][0];
  125.     }
  126.  
  127.     //plug sort information into global HAVE_SORTED_BY variable
  128.     HAVE_SORTED_BY[0]=sortCol;
  129.     HAVE_SORTED_BY[1]=subsortCol;
  130.     HAVE_SORTED_BY[2]=findObject("sortType").selectedIndex;
  131.     HAVE_SORTED_BY[3]=findObject("subsortType").selectedIndex;
  132.     HAVE_SORTED_BY[4]=findObject("sortOrder").selectedIndex;
  133.     HAVE_SORTED_BY[5]=findObject("subsortOrder").selectedIndex;
  134.     HAVE_SORTED_BY[6]=findObject("sortFirstRow").checked;
  135.     
  136.     //restore original selection
  137.     selArr = dreamweaver.nodeToOffsets(tableObj);
  138.     dreamweaver.setSelection(selArr[0],selArr[1]);
  139.     
  140.     MM.clearBusyCursor();
  141. }
  142.  
  143. function compareCallback(a,b){
  144.    var retVal=0;
  145.    var result=0;
  146.    //determine whether to switch a and b based on a and b values and specified sort order
  147.    //if -1 is returned: order stays the same, if 1: values are switched, if 0: values are equal
  148.  
  149.   if (findObject("sortType").selectedIndex==0)
  150.      result = LocaleSort.compareString(a[1],b[1]);
  151.    else
  152.      if (a[1]!=b[1])
  153.        result = (a[1]<b[1])?-1:1; 
  154.  
  155.    if (result!=0)
  156.      retVal=(result)*(findObject("sortOrder").selectedIndex==0?1:-1);
  157.    else { 
  158.      if (findObject("subsortType").selectedIndex==0)
  159.        result = LocaleSort.compareString(a[2],b[2])  
  160.      else {
  161.        if (a[2]!=b[2])
  162.          result = (a[2]<b[2])?-1:1;
  163.      }
  164.      if (result!=0)
  165.        retVal=(result )*(findObject("subsortOrder").selectedIndex==0?1:-1);
  166.    }
  167.  
  168.  
  169.    return retVal;
  170. }
  171.  
  172. function initializeUI(){
  173.    var colCount;
  174.    var tableObj = findTable();
  175.  
  176.    if (hasSpans(tableObj)){ //if table has rowspans or colspans
  177.       findObject("ErrMsgLayer").innerHTML="<p> " + MSG_SpansArePresent;
  178.       findObject("formLayer").visibility = "hidden";
  179.       findObject("ErrMsgLayer").visibility="visible";
  180.     } else if (hasCaption(tableObj)){
  181.       findObject("ErrMsgLayer").innerHTML="<p> " + MSG_CaptionIsPresent;
  182.       findObject("formLayer").visibility = "hidden";
  183.       findObject("ErrMsgLayer").visibility="visible";
  184.      }else if (isInvalidTable(tableObj)){ //if table is invalid
  185.       findObject("ErrMsgLayer").innerHTML="<p> " + MSG_IsInvalidTable;
  186.       findObject("formLayer").visibility = "hidden";
  187.       findObject("ErrMsgLayer").visibility="visible";
  188.       } else { //if everything is okay
  189.  
  190.       //dynamically update all form elements
  191.       //dynamically update sort order and type
  192.       with (findObject("sortType")){
  193.         options[0]= new Option(MENU_TypeAlphabetical);
  194.         options[1]= new Option(MENU_TypeNumerical);
  195.       }
  196.       with (findObject("subsortType")){
  197.         options[0]= new Option(MENU_TypeAlphabetical);
  198.         options[1]= new Option(MENU_TypeNumerical);
  199.       }
  200.       with (findObject("sortOrder")){
  201.         options[0]= new Option(MENU_OrderAscending);
  202.         options[1]= new Option(MENU_OrderDescending);
  203.       }
  204.       with (findObject("subsortOrder")){
  205.         options[0]= new Option(MENU_OrderAscending);
  206.         options[1]= new Option(MENU_OrderDescending);
  207.       }
  208.       //dynamically update sortCol and subsortCol menus
  209.       colCount=tableObj.childNodes.item(0).childNodes.length;
  210.       for (i=0;i<colCount;i++)
  211.         findObject("sortCol").options[i]=new Option(MENU_Column + " " + (i+1)); 
  212.       findObject("subsortCol").options[0]=new Option(" ");
  213.       for (i=0;i<colCount;i++)
  214.         findObject("subsortCol").options[i+1]=new Option(MENU_Column + " " + (i+1)); 
  215.    }
  216. }
  217.  
  218. function parseNumber(value){
  219.  
  220.   var retVal=value;
  221.   var numLength = retVal.length;
  222.   var k=0;
  223.  
  224.   //before sorting as numbers, remove % and $ symbols 
  225.   if (retVal.charAt(0)=="$")
  226.     retVal=retVal.slice(1);
  227.   else if (retVal.charAt(numLength-1)=="%" || retVal.charAt(numLength-1)=="$")
  228.     retVal=retVal.slice(0,-1);
  229.   
  230.   //before sorting as numbers, remove spaces and turn commas into decimal points
  231.   while( retVal.charAt(k) ){ 
  232.     if (retVal.charAt(k)==" "){ 
  233.       retVal=retVal.substring(0,k) + retVal.substring(k+1);continue; 
  234.     }
  235.     if (retVal.charAt(k)==","){ 
  236.        retVal=retVal.substring(0,k) + retVal.substring(k+1);continue; 
  237.     }   
  238.     k++;
  239.   }
  240.    
  241.   //following lines exist to work around Netscape crash caused by comparing
  242.   //two values that are both NaN. Workaround: Non-numbers are treated as strings.
  243.   if (parseFloat(retVal) == retVal)
  244.     retVal = parseFloat(retVal);
  245.     
  246.   return retVal;
  247. }
  248.  
  249.  
  250.  
  251. function hasSpans(theObj){ //checks for rowspans and colspans
  252.    var hasSpans=false;
  253.    var tdIter=theObj.getElementsByTagName("TD");
  254.    var iterLength=tdIter.length;
  255.    
  256.    for (i=0;i<iterLength;i++){  //if any rowspan or colspan attributes are found, return true
  257.       if(tdIter.item(i).getAttribute("ROWSPAN") || tdIter.item(i).getAttribute("COLSPAN")){
  258.         hasSpans=true;
  259.         break;
  260.       }
  261.    }
  262.    return hasSpans;
  263. }
  264.  
  265. function hasCaption(theObj){
  266.   if (theObj.childNodes.item(0).tagName && theObj.childNodes.item(0).tagName=="CAPTION")
  267.     return true;
  268.   return false;
  269. }
  270.  
  271. function isInvalidTable(theObj){
  272.  
  273.   var retVal=false;
  274.   var trIter=theObj.childNodes;
  275.   var trIterLen = trIter.length;
  276.   var widthOfFirstRow=trIter.item(0).childNodes.length;
  277.  
  278.   //check that each child node of table is TR tag
  279.   //and that each TR has same number of children
  280.   //note that we use the childNodes to check the children number
  281.   //instead of getElementsByTagName("TD").length, because the latter
  282.   //would give deceiving results in the case of nested tables
  283.   for (i=0;i<trIterLen;i++){
  284.     if (trIter.item(i).tagName != "TR" || trIter.item(i).childNodes.length==0
  285.             || trIter.item(i).childNodes.length!=widthOfFirstRow){
  286.       retVal=true; break;
  287.     }
  288.   }
  289.   return retVal;
  290. }
  291.  
  292.  
  293. function getTextNode(theObj){
  294.     var iter=theObj.childNodes;
  295.     var counter=0;
  296.     var child=iter.item(counter);
  297.     var retVal="";
  298.  
  299.    while (child) {
  300.       retVal+=getTextNode(child);
  301.       child=iter.item(++counter);
  302.    }
  303.      if (theObj.nodeType == Node.TEXT_NODE)
  304.      retVal+=theObj.data;
  305.    
  306.    return retVal;
  307. }
  308.  
  309. function gobbleWhiteSpace(textstring){
  310.   var lastChar,counter=0;
  311.   var whiteSpaceChars = " \n\r\f\t";
  312.  
  313.   //gobble whitespace from beginning of string
  314.   while (  textstring && whiteSpaceChars.indexOf( textstring.charAt(0) ) !=  -1  ){
  315.     textstring = textstring.substring(1);
  316.   }
  317.     
  318.   //gobble whitespace from end of string
  319.   lastChar = textstring.length-1;
  320.   while (  textstring && whiteSpaceChars.indexOf( textstring.charAt(lastChar) ) != -1  ){
  321.      textstring = textstring.substring(0,lastChar--);
  322.   }
  323.         
  324.   return textstring;  
  325. }    
  326.  
  327. //**************** GENERIC FUNCTIONS ****************
  328.  
  329. function findObject(objName,  parentObj) {
  330.   var i,tempObj="",found=false,curObj = "";
  331.   var NS = (navigator.appName.indexOf("Netscape") != -1);
  332.   if (!NS && document.all) curObj = document.all[objName]; //IE4
  333.   else {
  334.     parentObj = (parentObj != null)? parentObj.document : document;
  335.     if (parentObj[objName] != null) curObj = parentObj[objName]; //at top level
  336.     else { //if in form
  337.       if (parentObj.forms) for (i=0; i<parentObj.forms.length; i++) {  //search level for form object
  338.         if (parentObj.forms[i][objName]) {
  339.           curObj = parentObj.forms[i][objName];
  340.           found = true; break;
  341.       } }
  342.       if (!found && NS && parentObj.layers && parentObj.layers.length > 0) {
  343.         parentObj = parentObj.layers;
  344.         for (i=0; i<parentObj.length; i++) { //else search for child layers
  345.           tempObj = findObject(objName,parentObj[i]); //recurse
  346.           if (tempObj) { curObj = tempObj; break;} //if found, done
  347.   } } } }
  348.   return curObj;
  349. }
  350.